#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/platform_device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/rational.h>
#include <linux/reset.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <linux/proc_fs.h>

#include <asm/irq.h>


// 自己写的circualbuf
#include "crc_buf.h"

#define CRC_SIZE 1024
static buffer_t * send_buf = NULL;
static buffer_t * recv_buf = NULL;
static struct proc_dir_entry *uart_proc_file;
static struct uart_port	*virt_port;
static struct uart_driver virt_uart_drv = {
	.owner          = THIS_MODULE,
	.driver_name    = "VIRT_UART",
	.dev_name       = "ttyVIRT",
	.major          = 0,
	.minor          = 0,
	.nr             = 1, //提前定义好的 驱动就支持1个port
};

static int rx_buf_w = 0;
static const struct of_device_id virtual_uart_of_match[] = {
	{ .compatible = "lcs,virtual_uart", },
	{ },
};
static unsigned int virt_tx_empty(struct uart_port *port)
{
	/* 因为要发送的数据瞬间存入buffer */
	return 1;
}

static void virt_start_tx(struct uart_port *port)
{
	// 行规程会把数据放在circual_buf里面需要我们取出来
	struct circ_buf *xmit = &port->state->xmit;
	char data;
	while (!uart_circ_empty(xmit) &&
	       !uart_tx_stopped(port) && rb_remain(send_buf)) {
		/* send xmit->buf[xmit->tail]
		 * out the port here */
		data = xmit->buf[xmit->tail];
		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		send_buf->buf[send_buf->tail & (send_buf->size - 1)] = data;
        send_buf->tail++;
		port->icount.tx++;
	}

   if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
	   uart_write_wakeup(port);

}
static void
virt_set_termios(struct uart_port *port, struct ktermios *termios,
		  struct ktermios *old)
{
   return;
}
static int virt_startup(struct uart_port *port)
{
   return 0;
}

static void virt_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
}

static unsigned int virt_get_mctrl(struct uart_port *port)
{
   return 0;
}

static void virt_stop_tx(struct uart_port *port)
{
}

static void virt_stop_rx(struct uart_port *port)
{
}

static void virt_shutdown(struct uart_port *port)
{
}

static const char *virt_type(struct uart_port *port)
{
   return "100ASK_VIRT_UART";
}
static const struct uart_ops virt_pops = {
   .tx_empty   = virt_tx_empty,
   .set_mctrl  = virt_set_mctrl,
   .get_mctrl  = virt_get_mctrl,
   .stop_tx    = virt_stop_tx,
   .start_tx   = virt_start_tx,
   .stop_rx    = virt_stop_rx,
   //.enable_ms    = imx_enable_ms,
   //.break_ctl    = imx_break_ctl,
   .startup    = virt_startup,
   .shutdown   = virt_shutdown,
   //.flush_buffer = imx_flush_buffer,
   .set_termios    = virt_set_termios,
   .type	   = virt_type,
   //.config_port  = imx_config_port,
   //.verify_port  = imx_verify_port,
};


// 这里通过文件操作直接read 看看uart是不是真的把串口write的数据写到了send_buf的里面
ssize_t virt_uart_buf_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
	/* 把txbuf中的数据copy_to_user */
    // 这里读的是虚拟串口发送的数据
	int cnt = buffer_len(send_buf);
	int ret;

	cnt = (cnt > size)? size: cnt;
	ret = buffer_remove(send_buf,buf,cnt);
	return cnt;
}
// 而write就会直接触发中断了 中断把数据上报给行规程不经过驱动程序了 此时可能有个uar应用正在等待read 就会读到了
static ssize_t virt_uart_buf_write (struct file *file, const char __user *buf, size_t size, loff_t *off)
{

	/* get data */
	// 自己写无所谓循环不循环的
	rx_buf_w = buffer_add(recv_buf,buf,size);

	/* 模拟产生RX中断 */
	irq_set_irqchip_state(virt_port->irq, IRQCHIP_STATE_PENDING, 1);
	
	return size;
}
// 这个是对内个文件夹的操作 不是主要的是测试用的
static const struct file_operations virt_uart_buf_fops = {
	.read		= virt_uart_buf_read,
	.write		= virt_uart_buf_write,
};

static irqreturn_t virt_uart_rxint(int irq, void *dev_id)
{
	struct uart_port *port = dev_id;
	struct tty_port *tport = &port->state->port;
	unsigned long flags;
	
	spin_lock_irqsave(&port->lock, flags);
	// 先这么简化写看看能不能用
	buffer_report_to_tty(recv_buf, tport, rx_buf_w);
	rx_buf_w = 0;
	spin_unlock_irqrestore(&port->lock, flags);
	
	
	return IRQ_HANDLED;
}
static int virtual_uart_probe(struct platform_device *pdev)
{	
	int rxirq;
	int ret;
    uart_proc_file = proc_create("virt_uart_buf", 0, NULL, &virt_uart_buf_fops);
    rxirq = platform_get_irq(pdev,0);
    	/* 分配设置注册uart_port */
	virt_port = devm_kzalloc(&pdev->dev, sizeof(*virt_port), GFP_KERNEL);

	virt_port->dev = &pdev->dev;
	virt_port->iotype = UPIO_MEM;
	virt_port->irq = rxirq;
	virt_port->fifosize = 32;
	virt_port->ops = &virt_pops;  // 重点最终调用的就是这个
	virt_port->flags = UPF_BOOT_AUTOCONF;
	virt_port->type = PORT_8250;

    // 申请一个中断 当我们的串口接收到数据的时候就会触发这个中断
    // 中断触发后 向行规程上报数据
    ret = devm_request_irq(&pdev->dev, rxirq, virt_uart_rxint, 0,
				   dev_name(&pdev->dev), virt_port);
	send_buf = buffer_new(CRC_SIZE);
    recv_buf = buffer_new(CRC_SIZE);
	return uart_add_one_port(&virt_uart_drv, virt_port);
}
static int virtual_uart_remove(struct platform_device *pdev)
{
	uart_remove_one_port(&virt_uart_drv, virt_port);
	proc_remove(uart_proc_file);
	if(send_buf)
		buffer_free(send_buf);
	if(recv_buf)
		buffer_free(recv_buf);
	return 0;
}
static struct platform_driver virtual_uart_driver = {
	.probe		= virtual_uart_probe,
	.remove		= virtual_uart_remove,
	.driver		= {
		.name	= "100ask_virtual_uart",
		.of_match_table = of_match_ptr(virtual_uart_of_match),
	}
};
static int __init virtual_uart_init(void)
{	
	int ret;

	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	
	ret = uart_register_driver(&virt_uart_drv);

	if (ret)
		return ret;
	
	/* 1.1 注册一个platform_driver */
	return platform_driver_register(&virtual_uart_driver);
}
static void __exit virtual_uart_exit(void)
{
	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	/* 2.1 反注册platform_driver */
	platform_driver_unregister(&virtual_uart_driver);

	
	uart_unregister_driver(&virt_uart_drv);
}

module_init(virtual_uart_init);
module_exit(virtual_uart_exit);

MODULE_LICENSE("GPL");